package com.spic.business.common.workflow;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spic.business.common.core.workflow.IWorkFlowService;
import com.spic.business.common.core.workflow.IWorkFlowType;
import com.spic.business.common.core.workflow.WorkFlowEntity;
import com.spic.common.core.constant.SecurityConstants;
import com.spic.common.core.domain.R;
import com.spic.common.core.web.domain.AjaxResult;
import com.spic.system.api.RemoteActivitiTaskService;
import com.spic.system.api.RemoteStatus;
import com.spic.system.api.domain.ActTaskStartDto;
import com.spic.system.api.domain.BusinessStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * @Description 工作流程服务实现类
 * Notice: 本服务基于MybatisPlus, 实体类没有对应表的属性要加注解@TableField(exist = false)；Mapper要继成BaseMapper
 * @Author AnQi
 * @Date 2021/11/17
 */
public abstract class WorkFlowServiceImpl<M extends BaseMapper<T>, T extends WorkFlowEntity> extends ServiceImpl<M, T> implements IWorkFlowService<T> {

    @Autowired
    private RemoteActivitiTaskService ActivityService;
    @Autowired
    private RemoteStatus remoteStatus;

    @Override
    @Transactional
//    @GlobalTransactional
    public void startFlow(String id) {
        T entity = this.getById(id);
        Map<String, Object> vars = new HashMap<>();
        setWorkFlowVariable(entity, vars);
        ActTaskStartDto dto = new ActTaskStartDto();
        IWorkFlowType workFlowType = getWorkFlowType();
        dto.setKey(workFlowType.getKey())
            .setBusinessType(workFlowType.getBusinessType())
            .setInstanceName(workFlowType.getInstanceName())
            .setBusiness(id)
            .setVars(vars);
        AjaxResult result = ActivityService.startInstance(dto, SecurityConstants.INNER);
        //回写instanceId
        String instanceId = result.get("data").toString();
        baseMapper.update(null, new UpdateWrapper<T>().eq("id", id).set("instance_id", instanceId));
    }

    /**
     * 获取工作流类型
     * @return
     */
    protected abstract IWorkFlowType getWorkFlowType();

    /**
     * 设置流程变量
     */
    protected abstract void setWorkFlowVariable(T entity, Map<String, Object> variable);

    /**
     * 通用处理每条记录，用于分页列表展示统一处理
     * @param list 返回列表
     * @param consumer 处理每条记录的方法
     */
    protected void processRow(List<T> list, Consumer<T> consumer){
        Map<String,BusinessStatus> statusMap =  getWorkFlowStatus(list);
        for (T t : list) {
            BusinessStatus businessStatus = statusMap.get(String.valueOf(t.getId()));
            if(businessStatus != null){
                t.setStatus(businessStatus.getStatus());
                t.setInstanceId(businessStatus.getProcessInstanceId());
            }
            if(consumer != null){
                consumer.accept(t);
            }
        }
    }

    /**
     * 获取流程状态
     * @param list
     * @return
     */
    protected Map<String,BusinessStatus> getWorkFlowStatus(List<T> list){
        if(CollectionUtils.isEmpty(list)) return Collections.EMPTY_MAP;
        List<String> ids = list.stream().map(item->item.getId().toString()).collect(toList());
        R<List<BusinessStatus>> rList = remoteStatus.getStateBybusinessIds(getWorkFlowType().getBusinessType(), ids);
        List<BusinessStatus> businessStatusesList = rList.getData();
        if(businessStatusesList!=null){
            return businessStatusesList.stream().collect(Collectors.toMap(BusinessStatus::getBusinessKey, Function.identity(), (key1, key2) -> key2));
        }
        return Collections.EMPTY_MAP;
    }


}
